const express = require("express");
const router = express.Router();
const axios = require("axios");
const utils = require("../utils/index.js");
const xml2js = require("xml2js"); // 用于将XML数据转换为JavaScript对象
const bodyparser = require("body-parser");
const pool = require("../pool.js");
const moment = require("moment-timezone");
const path = require("path");
const archiver = require("archiver");
const msgUtils = require("../utils/feishu.js");

const parser = new xml2js.Parser({
    preserveChildrenOrder: true,
    explicitChildren: true,
});
const multer = require("multer");
const fs = require("fs");
const requestRegistry = new Map();
// 内存中的标志对象，作为Redis的替代品，用于防止重复提交
const taskInProgress = {};

// 配置Multer以使用本地磁盘存储
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "uploads/"); // 确保这个目录已经存在或者你在代码中创建它
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname); // 使用日期时间来构建一个唯一的文件名
    },
});

const upload = multer({ storage: storage });

router.post("/gptTranslate", async (req, res) => {
    const { language, translateText } = req.body;
    const url = "https://chatai.wecall.info/chat_new";
    const data = {
        query: `Translate the following text to ${language} language: ${translateText}`,
        code: "961234",
    };

    const headers = {
        "Content-Type": "application/json",
    };

    axios
        .post(url, data, { headers: headers })
        .then((response) => {
            res.send(
                utils.returnData({
                    data: response.data,
                })
            );
        })
        .catch((error) => {
            res.send(utils.returnData({ code: -1, error, req }));
        });
});
function extractVersion(xmlContent) {
    const versionRegex = /<!--\s*version\s*=\s*([\d.\s]+)\s*-->/;
    const match = xmlContent.match(versionRegex);
    if (match) {
        // 移除所有空白字符
        return match[1].replace(/\s+/g, '');
    }
    return null;
}
router.post("/uploadXML", upload.single("xmlFile"), async (req, res) => {
    let { name } = await utils.getUserInfo(req, res);
    // 上传的文件信息在req.file
    if (!req.file) {
        return res.status(400).send("No file uploaded.");
    }
    let { packageName } = req.body;

    // 读取上传的XML文件
    fs.readFile(req.file.path, async (err, data) => {
        if (err) {
            return res.status(500).send("Error reading uploaded file");
        }
        // 这里我们直接将Buffer转换成字符串，得到XML的原始内容
        let rawXML = data.toString();
        let strMatch = /<!--LANG_INCLUDE=(.*?)-->/i;
        if (rawXML.includes("LANG_INCLUDE")) {
            strMatch = /<!--LANG_INCLUDE=(.*?)-->/i;
        }
        if (rawXML.includes("LANG INCLUDE")) {
            strMatch = /<!--LANG INCLUDE=(.*?)-->/i;
        }
        let newFindContent = rawXML.replace(/ /g, "");
        let matches = newFindContent.match(strMatch);
        // 提取版本号
        const version = extractVersion(rawXML);
        if (!version) return res.send({ code: 1, msg: "缺少版本信息" })
        // 如果有匹配结果，处理这些结果
        if (matches) {
            let langInclude = matches[1]; // 获取括号中匹配的内容
            let languageCodes = langInclude.split(","); // 用逗号分割语言代码
            let queryId = "";
            //判断库里有没有 有就更新 没有就新增  insert
            let sql = `select * from js_app_translation_task where package_name = '${packageName}' and version = '${version}'`;
            const insertResult = await selectTranslationTask(sql);
            if (insertResult.length == 0) {
                //新增 js_app_translation_task
                let AppTranslationTask = {
                    id: utils.createId(),
                    package_name: packageName,
                    flag: 0,
                    create_by: name,
                    update_by: name,
                    submit_status: 0,
                    create_time: utils.formatDate(new Date()),
                    update_time: utils.formatDate(new Date()),
                    version: version,
                };
                queryId = AppTranslationTask.id;
                const { text, values } = utils.createInsertSql(
                    "js_app_translation_task",
                    AppTranslationTask
                );
                let result = await utils.query(text, values);
            } else {
                queryId = insertResult[0].id;
                //更新 js_app_translation_task
                let updateSql = `UPDATE js_app_translation_task SET  update_by = '${name}', update_time = '${utils.formatDate(
                    new Date()
                )}' WHERE package_name = '${packageName}' and version = '${version}'`;
                await pool.query(updateSql, (updateErr, updateResult) => {
                    if (updateErr)
                        return res.send(utils.returnData({ code: -1, updateErr, req }));
                });
            }

            // js_app_translation_child_task
            let l = await bathSaveString(
                rawXML,
                languageCodes,
                packageName,
                queryId,
                langInclude,
                name,
                version
            );
            console.log('--------------进来了lllllllllllllllllllllll----------------------', l)

            if (l > 0) {

                console.log('有新的更新---------------------------')
                //有新的更新 更新js_app_translation_task表  把flag设置为0
                let updataSqlFlag = `UPDATE js_app_translation_task SET  flag = '0' ,submit_status = '0', update_by='${name}', update_time = '${utils.formatDate(
                    new Date()
                )}' WHERE package_name = '${packageName}' and version = '${version}'`;
                let o = await updateTranslationTaskFlag(updataSqlFlag);
                //更新数据至js_app_translation_file表  1。先查询有没有，有就更新  没有就新增  把state设置为0
                let querySql = `select * from js_app_translation_file where package_name = '${packageName}' and version='${version}'`;
                let queryRes = await mysqlQuery(querySql);
                if (queryRes.length == 0) {
                    //新增 js_app_translation_file
                    let AppTranslationFile = {
                        id: utils.createId(),
                        package_name: packageName,
                        create_by: name,
                        update_by: name,
                        create_time: utils.formatDate(new Date()),
                        update_time: utils.formatDate(new Date()),
                        state: 0,
                        file_path: "/zj-manager/app-file/" + packageName,
                        file_content: rawXML,
                        file_language: langInclude,
                        version: version,
                    };
                    const { text, values } = utils.createInsertSql(
                        "js_app_translation_file",
                        AppTranslationFile
                    );
                    let FileResult = await utils.query(text, values);
                } else {
                    //更新 js_app_translation_file
                    let updateFileSql = `UPDATE js_app_translation_file SET  update_by = '${name}',state = '0',file_language='${langInclude}',file_content='${rawXML}', update_time = '${utils.formatDate(
                        new Date()
                    )}' WHERE package_name = '${packageName}' and version = '${version}'`;
                    await pool.query(updateFileSql, (updateErr, updateResult) => {
                        if (updateErr)
                            return res.send(utils.returnData({ code: -1, updateErr, req }));
                    });
                }
            }
            let updateFileSql = `UPDATE js_app_translation_file SET  update_by = '${name}',state = '0', file_language='${langInclude}', update_time = '${utils.formatDate(
                new Date()
            )}' WHERE package_name = '${packageName}' and version = '${version}'`;
            await pool.query(updateFileSql, (updateErr, updateResult) => {
                if (updateErr)
                    return res.send(utils.returnData({ code: -1, updateErr, req }));
            });
            setTimeout(() => {
                // 处理完成后删除上传的文件
                fs.unlink(req.file.path, (err) => {
                    if (err) {
                        console.error('Failed to delete uploaded file:', err);
                    } else {
                        console.log('Uploaded file deleted successfully');
                    }
                });
            }, 500)
            let appNotice = {
                pk: packageName,
                version: version,
                type: 1,
            }
            await checkThresholdLimit(appNotice)
            res.send({ code: 0, msg: "操作成功" });
        } else {
            // 没有找到匹配的内容
            console.log("No matching content found LANG_INCLUDE");
            // 返回或处理错误情形
            fs.unlink(req.file.path, () => { // 删除上传的文件
                return res.status(400).send("No matching content found LANG_INCLUDE.");
            });
        }
    });
});





async function getTranslationStatus(childTask) {
    return new Promise((resolve, reject) => {
        pool.query(`SELECT COUNT(1) AS count 
         FROM js_app_translation_child_task 
         WHERE package_name = ? AND version = ?  AND child_flag = '0' 
        `, [childTask.packageName, childTask.version, childTask.taskRootId], (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results[0].count);
        });
    });
}

async function getSubmitStatus(childTask) {
    return new Promise((resolve, reject) => {
        pool.query(`SELECT COUNT(1) AS count 
         FROM js_app_translation_child_task 
         WHERE package_name = ? AND version = ? AND submit_status = '0' 
         AND child_flag != '2' 
         `, [childTask.packageName, childTask.version, childTask.taskRootId], (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results[0].count);
        });
    });
}


async function getAppTranslationChildTask(packageName, version) {
    return new Promise((resolve, reject) => {
        pool.query(`SELECT * FROM js_app_translation_child_task WHERE package_name = '${packageName}' AND version = '${version}'`, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}

async function setSubmitStatus(packageName, version) {
    return new Promise((resolve, reject) => {
        pool.query(`UPDATE js_app_translation_child_task set submit_status ='1',update_time = '${utils.formatDate( new Date() )}'
        WHERE  package_name=  '${packageName}' AND version = '${version}'`, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
async function setSubmitStatusTask(packageName, version, status) {
    return new Promise((resolve, reject) => {
        pool.query(`UPDATE js_app_translation_task set submit_status ='${status}',update_time = '${utils.formatDate(new Date())}'
        WHERE  package_name=  '${packageName}' AND version = '${version}'`, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}

async function setSubmitflag(packageName, version) {
    return new Promise((resolve, reject) => {
        pool.query(`UPDATE js_app_translation_task set flag ='1',update_time = '${utils.formatDate(new Date())}'
        WHERE  package_name=  '${packageName}' AND version = '${version}'`, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}


async function getLangList(packageName, version) {
    return new Promise((resolve, reject) => {
        pool.query(`SELECT  * FROM js_app_translation_file WHERE package_name ='${packageName}' AND version = '${version}'`, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            // let langList = results[0].file_language
            // const split = langList.split(',');
            // const mapList = split.map(lang => {
            //     return { label: lang, value: lang };
            // });
            resolve(results[0].file_language);
        });
    });
}
router.post('/getLangListByPk', async (req, res) => {
    const { package_name, version } = req.body
    let sql = `SELECT DISTINCT target_language FROM js_app_translation_child_task WHERE package_name = '${package_name}' AND version = '${version}'`
    pool.query(sql, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        res.send({
            code: 0,
            data: result
        })
    })
})

async function createXmlFile(packageName, version) {
    let basePath = "/zj-manager/app-file/" + packageName;
    // let basePath = "/uploads/" + packageName;
    // let basePath = path.join(__dirname, '../', "uploads", packageName);

    try {

        const childTaskList = await getAppTranslationChildTask(packageName, version);
        const appTranslationChildTask = childTaskList.reduce((acc, task) => {
            const lang = task.target_language.trim();
            if (lang === "id") task.target_language = "in-rID";
            if (!acc[lang]) acc[lang] = [];
            acc[lang].push(task);
            return acc;
        }, {});

        const langList = await getLangList(packageName, version);
        const strLanguage = "<!-- LANG_INCLUDE=" + langList + " -->";
        const strVersion = "<!-- version=" + version + " -->";
        const tempDirectories = [];
        for (const [targetLang, tasks] of Object.entries(appTranslationChildTask)) {
            const langDir = path.join(basePath, `values-${targetLang}/`);
            tempDirectories.push(langDir);  // 记录创建的目录，稍后删除
            let sb = strLanguage + "\n" + strVersion + "\n<resources>";
            tasks.forEach(task => {
                const content = unescapeXML(dealStringContent(task.string_content));
                let translation = ''
                if (task.translation_result) {
                    translation = unescapeXML(dealStringContent(task.translation_result.replace("\n", "\\n")));  //后面解开注释
                }
                if (task.string_type === "0" && task.child_flag === "2") {
                    // string 标签  translatable="false"
                    sb += `\n<string name="${task.string_name}" translatable="false">${content}</string>`;
                } else if (task.string_type === "1" && task.child_flag === "2") {
                    // 处理 translatable="false" 的 string-array 标签
                    const stringArray = content.split(',').map(item => `<item>${item.trim()}</item>`).join('\n');
                    sb += `\n<string-array name="${task.string_name}" translatable="false">\n${stringArray}\n</string-array>`;
                } else if (task.string_type === "1") {
                    // 处理普通的 string-array 标签
                    const stringArray = translation.split(',').map(item => `<item>${item.trim()}</item>`).join('\n');
                    sb += `\n<string-array name="${task.string_name}">\n${stringArray}\n</string-array>`;
                } else {
                    // string 标签
                    sb += `\n<string name="${task.string_name}">${translation}</string>`;
                }
            });
            sb += "\n</resources>";

            // 直接写入本地文件系统
            await writeFileAsync(langDir, "strings.xml", sb);
        }

        const zipFilePath = path.join(basePath, `${packageName}-${version}.zip`);
        // 创建压缩包，包含语言目录
        const zipResult = await createZipWithDirectories(basePath, tempDirectories, zipFilePath);
        console.log(`Zip file created successfully at ${zipFilePath}`);

        if (!zipResult) {
            throw new Error(`Failed to create zip file at path: ${zipFilePath}`);
        }

        console.log(`Zip file created successfully at ${zipFilePath}`);
        let appNotice = {
            pk: packageName,
            version: version,
            type: 3,
        }
        await checkThresholdLimit(appNotice)
        // 删除临时文件夹，保留最终的zip文件
        tempDirectories.forEach(deleteFolderRecursive);

        return zipFilePath;
    } catch (err) {
        console.error(`Error: ${err.message}`);
        return null;
    }
}
function deleteFolderRecursive(directoryPath) {
    if (fs.existsSync(directoryPath)) {
        fs.readdirSync(directoryPath).forEach((file) => {
            const currentPath = path.join(directoryPath, file);
            if (fs.lstatSync(currentPath).isDirectory()) {
                // 递归删除目录
                deleteFolderRecursive(currentPath);
            } else {
                // 删除文件
                fs.unlinkSync(currentPath);
            }
        });
        fs.rmdirSync(directoryPath);
    }
}
function unescapeXML(str) {
    return str.replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&')
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/\\\\/g, '\\'); // 处理双反斜杠
}

// 处理字符串内容
function dealStringContent(content) {
    // 在这里处理字符串内容的转义等
    return content.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

// 写入文件
async function writeFileAsync(dir, filename, content) {
    try {
        fs.mkdirSync(dir, { recursive: true });
        fs.writeFileSync(path.join(dir, filename), content, 'utf-8');
        console.log(`Successfully wrote file: ${path.join(dir, filename)}`);
        return true;
    } catch (err) {
        console.error(`File write error: ${err.message}`);
        return false;
    }
}

// 压缩目录

async function createZipWithDirectories(basePath, directories, zipFilePath) {
    const output = fs.createWriteStream(zipFilePath);
    const archive = archiver('zip', { zlib: { level: 9 } });

    return new Promise((resolve, reject) => {
        output.on('close', () => {
            console.log(`压缩文件成功创建并完全写入磁盘, 大小: ${archive.pointer()}`);
            resolve(true);
        });
        output.on('end', () => resolve(true));
        archive.on('warning', err => {
            if (err.code !== 'ENOENT') reject(err);
        });
        archive.on('error', err => reject(err));

        archive.pipe(output);
        directories.forEach(directory => {
            archive.directory(directory, path.basename(directory));
        });
        archive.finalize();
    });
}

async function notifyFeishu(packageName, langList) {
    // 在这里你可以使用 node-fetch 或任何其他HTTP客户端来通知飞书生成报告
    const fetch = require('node-fetch');

    const response = await fetch('https://feishu-notification-url', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            packageName: packageName,
            langs: langList
        })
    });

    return response.json();
}

router.post('/saveSubmit', async (req, res) => {
    try {
        const appTranslationTask = req.body;

        const translationChildTask = {
            packageName: appTranslationTask.packageName,
            taskRootId: appTranslationTask.id,
            version: appTranslationTask.version
        };

        // 检查是否有未翻译的内容
        const translationStatus = await getTranslationStatus(translationChildTask);
        if (translationStatus > 0) {
            return res.json({ success: false, message: "当前存在未翻译的内容，请全部翻译完再提交" });
        }

        // 检查是否有新的提交内容
        const submitStatus = await getSubmitStatus(translationChildTask);
        if (submitStatus < 1) {
            return res.json({ success: false, message: "当前任务没有新的内容需要提交" });
        }

        const cacheKey = `appxml:${appTranslationTask.packageName}`;
        if (requestRegistry.has(cacheKey)) {
            return res.json({ success: true, message: "已提交，正在生成文件，大约需要几分钟，耐心等待" });
        } else {
            requestRegistry.set(cacheKey, true);

            // 在一定时间后删除缓存标识，防止重复提交
            setTimeout(() => {
                requestRegistry.delete(cacheKey);
            }, 5 * 60 * 1000);
        }

        async function generateXmlFileTask() {
            try {
                const zipFilePath = await createXmlFile(appTranslationTask.packageName, appTranslationTask.version);
                console.log(`Generated zip file: ${zipFilePath}`);

                // 更新任务状态  submit_status
                await setSubmitStatus(appTranslationTask.packageName, appTranslationTask.version);
                await setSubmitflag(appTranslationTask.packageName, appTranslationTask.version);
                //更新 js_app_translation_task 表的 submit_status
                await setSubmitStatusTask(appTranslationTask.packageName, appTranslationTask.version, 1);


                // 通知飞书（伪代码）
                // await notifyFeishu(appTranslationTask.packageName, "langs");

                requestRegistry.delete(cacheKey);
            } catch (e) {
                console.error(`Error generating XML file: `, e);
                requestRegistry.delete(cacheKey);
            }
        }

        // 使用nextTick将任务异步化
        process.nextTick(generateXmlFileTask);

        res.json({ success: true, message: "提交成功" });

    } catch (error) {
        console.error('Error:', error);
        res.json({ success: false, message: `Save Error: ${error.message}` });
    }
});









//获取列表
router.post("/getFileList", async (req, res) => {
    let { packageName } = req.body;
    let sql = `select * from js_app_translation_task where package_name = '${packageName}' ORDER BY update_time DESC`;
    await pool.query(sql, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        result.forEach((element) => {
            element.create_time = moment(element.create_time).format("YYYY-MM-DD HH:mm:ss");
            element.update_time = moment(element.update_time).format("YYYY-MM-DD HH:mm:ss");
        });
        res.send(
            utils.returnData({
                data: result,
            })
        );
    });
});

router.post('/saveChildBatch', async (req, res) => {
    let { name } = await utils.getUserInfo(req, res);

    try {
        const appTranslationChildTask = req.body;
        let translationMultiLangXml = appTranslationChildTask.translationMultiLangXml;
        if (!translationMultiLangXml) {
            return res.json(renderResult(false, "No Change Content Save Success"));
        }
        const list = JSON.parse(translationMultiLangXml);

        for (let i = 0; i < list.length; i++) {
            let e = list[i];
            e.package_name = appTranslationChildTask.packageName;
            e.translation_result = normalizeContent(e.translationResult.trim());
            e.string_name = appTranslationChildTask.stringName.trim();
            e.string_content = normalizeContent(appTranslationChildTask.stringContent.trim());
            e.target_language = e.targetLanguage.trim();
            e.update_time = utils.formatDate(new Date());
            e.translationResults = JSON.stringify(appTranslationChildTask.translationResults);
            e.child_flag = 1
            // 用字符串名和语言和version更新或插入
            let updateSql = `UPDATE js_app_translation_child_task 
                            SET submit_status=0, update_by = ?, translationResults = ?,string_content= ? ,child_flag = ?, update_time = ?,translation_result= ?
                            WHERE string_name = ? AND target_language = ? AND package_name = ? AND version = ?`;
            let updateValues = [
                name,
                e.translationResults,
                e.string_content,
                e.child_flag,
                e.update_time,
                e.translation_result,
                e.string_name,
                e.target_language,
                e.package_name,
                appTranslationChildTask.version
            ];

            const updateRes = await updateTranslationChildTask(updateSql, updateValues)
            await setSubmitStatusTask(e.package_name, appTranslationChildTask.version, 0)
        }

        res.json(renderResult(true, "Save Success"));

    } catch (error) {
        console.error(error);
        res.json(renderResult(false, "Save Error: " + error.message));
    }
})

router.post('/childTaskTranslateTextForMultiLang', async (req, res) => {
    const childTask = req.body;

    if (!childTask || !childTask.multiLang || !childTask.stringContent) {
        return res.status(400).send(renderResult(false, "Invalid input parameters"));
    }

    const multiLang = childTask.multiLang;
    const languages = multiLang.split(',');
    let translationResults = [];
    let failed = 0;

    for (let lang of languages) {
        lang = lang.trim();
        let translateRes; // 在循环最顶部声明变量

        try {
            let text = normalizeContent(childTask.stringContent);
            const response = await translateForApp(lang, text); // 调用翻译API

            translateRes = response.data;

            if (translateRes.answer.includes(`${text} -->`) || translateRes.answer.includes(`${text} ->`)) {
                translateRes.answer = translateRes.answer.replace(`${text} -->`, "").replace(`${text} ->`, "");
            }
            translateRes.answer = translateRes.answer.replace(/&(?![a-zA-Z]{1,8};)/g, "&amp;");

            let answer = translateRes.answer;
            if (answer.includes("&amp;")) {
                answer = answer.replace(/&amp;/g, "&");
            }
            answer = answer.replace(/'/g, "\\'").replace(/＂/g, "\"");

            translationResults.push({ targetLanguage: lang, translationResult: answer });
        } catch (err) {
            console.error(`Error translating for language ${lang}: ${err.message}`);
            failed++;
        }
    }
    childTask.translationResults = translationResults
    childTask.translationMultiLang = translationResults.map(res => `${res.targetLanguage}:  ${res.translationResult}`).join('\n\n');
    childTask.translationMultiLangXml = JSON.stringify(translationResults);

    if (failed === 0) {
        res.send(renderResult(true, 'Translate success', childTask));
    } else if (failed > 0 && failed < languages.length) {
        res.send(renderResult(false, 'Partial translation successful'));
    } else {
        res.send(renderResult(false, 'Translation failed'));
    }
});


async function translateForApp(lang, stringText) {

    try {
        await new Promise(resolve => setTimeout(resolve, 20));
        // const url = "https://chatai.wecall.info/chat_new";
        // const jsonInputString = {
        //     query: `Translate the content into ${lang}, If the content I give you to translate has tags and styles, keep the HTML tags and styles unchanged. If not, don't add them. If I give you Unlock and ask you to translate it into an id, don't input something like Konten: Buka, just output Buka.${stringText}`,
        //     code: "961234",
        // };
        const url = "https://api.aitiming.net/v1/completion-messages";
        stringText = addSpaceAfterDPlaceholder(stringText); // 调用正则替换
        const jsonInputString = {
            inputs: {
                lang: lang,
                string: stringText
            },
            user: "abc-123"
        };

        const response = await axios.post(url, jsonInputString, {
            headers: {
                'Content-Type': 'application/json',
                'User-Agent': getUa(),
                'Authorization': 'Bearer app-JTWPQwcgOSXhcBDwE1UTpuwG',
                'Connection': 'keep-alive'
            },
            timeout: 180000 // 3 minutes
        });
        return response;
    } catch (error) {
        console.error(`Error in translateForApp: ${error.message}`);
        throw error;
    }
}

function addSpaceAfterDPlaceholder(input) {
    return input.replace(/%d(?=[A-Za-z0-9])/g, '%d ').replace(/%s(?=[A-Za-z0-9])/g, '%s ');
}

function getUa() {
    const uaList = [
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
    ];
    const randomNum = Math.floor(Math.random() * uaList.length);
    return uaList[randomNum];
}

function renderResult(success, message, data = null) {
    return {
        success,
        message,
        data
    };
}

// 分组函数
function groupByStringName(tasks) {
    return tasks.reduce((acc, task) => {
        const key = task.string_name;
        if (!acc[key]) {
            acc[key] = [];
        }
        acc[key].push(task);
        return acc;
    }, {});
}

// strForStyle 实现
function strForStyle(list, setMultiLang, sb) {
    sb.push("已翻译:\n");
    list.forEach((e) => {
        try {
            if (e.translation_result && e.translation_result.trim() !== "") {
                sb.push(`${e.target_language}: ${e.translation_result}\n`);
            }
            setMultiLang.add(e.target_language);
        } catch (err) {
            console.error(err);
        }
    });
}
router.post("/getChildTaskList", async (req, res) => {
    let { packageName, version, page, size } = req.body;

    const sqlParams = [];
    let sql = `select * from js_app_translation_child_task where package_name = '${packageName}' AND version = '${version}' ORDER BY id LIMIT ? OFFSET ?`;

    sqlParams.push(1000000, 0);
    await pool.query(sql, sqlParams, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        let childTasks = result;
        // 进行分组处理
        const groupedByStringContent = groupByStringName(childTasks);
        const childTaskList = [];
        Object.entries(groupedByStringContent).forEach(([k, v]) => {
            const childTask = {
                stringName: k,
                stringContent: v[0].string_content,
                multiLang: "",
                translationMultiLang: "",
                childFlag: "",
                translationMultiLangXml: v[0].translationMultiLangXml,
                translationResults: v[0].translationResults
            };
            const setMultiLang = new Set();
            const sb = [];
            strForStyle(v, setMultiLang, sb);

            childTask.multiLang = Array.from(setMultiLang).join(", ");
            let trimStr = sb.join("").trim();
            trimStr = trimStr.replace("已翻译:", "");

            if (!trimStr) {
                childTask.translationMultiLang = "未翻译";
            } else {
                childTask.translationMultiLang = sb.join("");
            }

            const collect = v.map((task) => task.child_flag);
            if (collect.includes("0")) {
                childTask.childFlag = "0";
            } else if (collect.includes("1")) {
                childTask.childFlag = "1";
            } else {
                childTask.childFlag = "2";
            }

            childTaskList.push(childTask);
        });
        // 确保 page 从 1 起始，避免 page = 0 的情况
        let currentPage = page <= 0 ? 1 : page;
        // 分页参数计算
        const startIndex = (currentPage - 1) * size;
        const endIndex = Math.min(startIndex + size, childTaskList.length);
        const paginatedList = childTaskList.slice(startIndex, endIndex);


        // 返回分页结果
        const pageResult = {
            data: paginatedList,
            pageNo: currentPage,
            pageSize: size,
            total: childTaskList.length,
        };

        res.json(pageResult);
    });
});
router.post("/getChildTaskListSingle", async (req, res) => {
    let { packageName, version, target_language } = req.body;
    let { page, size } = utils.pageSize(req.body.page, req.body.size);

    const sqlParams = [];
    let sql = `select * from js_app_translation_child_task where target_language = '${target_language}' and package_name = '${packageName}'  AND version = '${version}' ORDER BY id LIMIT ? OFFSET ?`;

    sqlParams.push(size, page);
    let { total } = await utils.getSum({
        name: "js_app_translation_child_task",
        where: `WHERE package_name ='${packageName}' AND target_language = '${target_language}' AND version = '${version}'`,
        res,
        req,
    });
    await pool.query(sql, sqlParams, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        let childTasks = result;
        childTasks.forEach(item => {
            item.stringContent = item.string_content
            item.childFlag = item.child_flag
            item.stringName = item.string_name
        })
        res.send(
            utils.returnData({
                data: childTasks,
                total: total,
            })
        );
    });
});
async function parseString(xmlContent) {
    return await parser.parseStringPromise(xmlContent);
}
// 提取字符串和字符串数组
function extractStringsAndArrays(xmlContent, xmlNode) {
    const strings = [];
    const regexString = /<string\s([^>]*?)name="(.*?)"(.*?)>(.*?)<\/string>/g;
    const regexStringArray =
        /<string-array\s([^>]*?)name="(.*?)"(.*?)>\s*([\s\S]*?)<\/string-array>/g;
    let match;

    while ((match = regexString.exec(xmlContent)) !== null) {
        const attributes = match[1].trim() + " " + match[3].trim(); // 合并前后属性
        strings.push({
            type: "string",
            name: match[2],
            content: match[4].trim(),
            attributes: attributes,
        });
    }

    while ((match = regexStringArray.exec(xmlContent)) !== null) {
        const items = match[4]
            .trim()
            .split(/<\/item>\s*<item>/)
            .map((item) => item.replace(/<\/?item>/g, "").trim() + ",");

        // 去除最后一个 `item` 末尾的多余逗号
        if (items.length > 0) {
            items[items.length - 1] = items[items.length - 1].replace(/,$/, "");
        }

        const attributes = match[1].trim() + " " + match[3].trim(); // 合并标签前后的属性

        strings.push({
            type: "string-array",
            name: match[2],
            items: items,
            attributes: attributes,
        });
    }

    return strings;
}
// 规范化字符串内容
function normalizeContent(content) {
    // 字面值替换
    content = content.replace(/＇/g, "'"); // 将全角单引号替换为半角单引号
    content = content.replace(/＂/g, '"'); // 将全角双引号替换为半角双引号

    // 正则表达式替换
    // JavaScript中无需多重转义 '\\'，因此修改为下述写法
    content = content.replace(/\\'/g, "'"); // 处理转义单引号

    // 如果意图是逐步处理半角单引号的转义，您可能不需要上述步骤，因为下一行已覆盖单引号的替换
    // 如果你要将结果存储到数据库或JSON中，你通常需要转义单引号
    content = content.replace(/'/g, "\\'"); // 将单引号替换为转义单引号，用于数据库或JavaScript字符串

    // 用于替换多个空白字符为空格
    content = content.replace(/\s+/g, " "); // 将多个空格替换为一个空格

    return content;
}
async function getStringKeyValue(name, languageCode, packageName, version) {
    return new Promise((resolve, reject) => {
        let sql = `SELECT * FROM js_app_translation_child_task WHERE package_name = ? AND string_name = ? AND target_language = ? AND version = ?`;
        let queryValues = [packageName, name, languageCode, version];
        pool.query(sql, queryValues, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
async function selectTranslationTask(sql) {
    return new Promise((resolve, reject) => {
        pool.query(sql, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
//更新js_app_translation_task表的flag
async function updateTranslationTaskFlag(sql) {
    return new Promise((resolve, reject) => {
        pool.query(sql, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
async function updateTranslationChildTask(sql, data) {
    return new Promise((resolve, reject) => {
        pool.query(sql, data, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
//查询表 
async function mysqlQuery(sql) {
    return new Promise((resolve, reject) => {
        pool.query(sql, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
// 检查字符串是否匹配特定模式
function matchesPattern(s) {
    s = s.trim();
    const patternString = "%d/\\d+";
    return new RegExp(patternString).test(s);
}
// 批量保存字符串
async function bathSaveString(xmlContent, languageCodes, packageName, taskId, langInclude, nameAuth, version) {
    try {
        let atomicInteger = 0;
        const document = await parseString(xmlContent);
        const strings = extractStringsAndArrays(xmlContent, document);
        for (const languageCode of languageCodes) {
            for (const item of strings) {
                let name = item.name;
                let content, items;
                if (item.type === "string") {
                    content = normalizeContent(item.content);
                } else if (item.type === "string-array") {
                    items = item.items.join("\n");
                }

                // 跳过没有值的项
                if (!name || (!content && !items)) {
                    continue;
                }
                // 设置 child_flag 根据 attributes
                // 设置 child_flag 根据 attributes 和内容
                let child_flag = 0;
                if (
                    item.attributes.includes('translatable="false"') ||
                    matchesPattern(content || items)
                ) {
                    child_flag = 2;
                }
                let string_type = item.type == "string" ? 0 : 1;


                // TODO: 检查是否已经存在这个字符串键值对
                let exists = await getStringKeyValue(name, languageCode, packageName, version);


                if (exists.length == 0) {//如果 exists.length==0 就代表是新增字段  就创建
                    // // 创建 childTask 对象，设置属性
                    let childTask = {
                        id: utils.createId(),
                        task_root_id: taskId,
                        string_content: content || items, // 添加内容或数组项
                        string_name: name.trim(),
                        target_language: languageCode.trim(),
                        child_flag: child_flag,
                        package_name: packageName,
                        create_by: nameAuth,
                        update_by: nameAuth,
                        create_time: utils.formatDate(new Date()),
                        update_time: utils.formatDate(new Date()),
                        string_type: string_type,
                        version: version,
                    };

                    //判断内容是否为空 在加childTask入库
                    const { text, values } = utils.createInsertSql(
                        "js_app_translation_child_task",
                        childTask
                    );
                    let result = await utils.query(text, values);
                    if (result) {
                        atomicInteger++;
                    }
                } else {
                    //如果存在,就比对content或者items的值  如果不同就更新
                    if (exists[0].string_content !== (item.type === "string" ? content : items)) {
                        console.log('--------------进来了----------------------')
                        // 如果 exists[0].string_content 不等于 (item.type 是 "string" ? content : items)，执行相应的操作
                        // 更新
                        let sqlUpdate = `UPDATE js_app_translation_child_task 
                     SET string_content = ?, 
                         translation_result = '', 
                         translationResults = '',
                         child_flag = '0',
                         submit_status = '0',
                         update_time = ?, 
                         create_by = ? 
                     WHERE id = ?`;
                        let updateValues = [
                            (item.type === "string" ? content : items),
                            utils.formatDate(new Date()),
                            nameAuth,
                            exists[0].id
                        ];

                        await pool.query(sqlUpdate, updateValues, (updateErr, updateResult) => {
                            if (updateErr) {
                                return res.send(utils.returnData({ code: -1, updateErr, req }));
                            }
                            res.send({ msg: "修改成功" });
                        });
                        atomicInteger++;
                        console.log('--------------进来了----------------------', atomicInteger)

                    }
                }


            }
        }

        return atomicInteger;
    } catch (e) {
        console.error("Error:", e.stack);
        return -1;
    }
}

//一键翻译
router.post('/oneClickTranslation', async (req, res) => {
    const { package_name, version } = req.body
    // 1. 查询 js_app_translation_task表的  flag如果等于2  说明正在执行翻译任务, 就return  正在翻译中 
    let querySql_task = `select * from js_app_translation_task where package_name = '${package_name}' and flag = 2 AND version = '${version}'`
    let querySql_task_flag2 = await mysqlQuery(querySql_task)
    console.log('querySql_task_flag2-------执行了第一步')
    if (querySql_task_flag2.length != 0) return res.send({ code: 1, message: '正在执行翻译任务中...' })

    // 2. 查询库里  有没有 child_flag = 0 未翻译的
    let querySql = `select * from js_app_translation_child_task where package_name = '${package_name}' and child_flag = 0 AND version = '${version}'`;
    let queryFlag0 = await mysqlQuery(querySql)
    console.log('queryFlag0-------执行了第二步')
    if (queryFlag0.length == 0) return res.send({ code: 1, message: '没有可执行任务' })
    let childTasks = queryFlag0  //要翻译的数组

    // 3. 有未翻译的  要开始翻译了  把 js_app_translation_task表的  flag设置为2 翻译中
    let setSql = `UPDATE js_app_translation_task  SET flag=2  WHERE  package_name = '${package_name}' AND version = '${version}'`
    let setSqlFlag2 = await mysqlQuery(setSql)
    console.log('setSqlFlag2-------执行了第三步')
    res.send({ code: 0, message: '操作成功,开始执行翻译任务!' })
    // 4. 循环这个数据  lang=item.lang  content = item.content  并更新翻译后的内容
    let taskRes = await appTranslateTextAddContentTranslateTask(childTasks)

    // 再次查验 看有没有漏掉没有翻译的
    let againQuerySql = `select * from js_app_translation_child_task where package_name = '${package_name}' and child_flag = 0 AND version = '${version}'`;
    let againQueryFlag0 = await mysqlQuery(againQuerySql)
    if (againQueryFlag0.length > 0) {
        console.log('有漏掉的--------------继续执行循环翻译')
        await appTranslateTextAddContentTranslateTask(againQueryFlag0)
    }

    // 5.翻译任务结束 处理合并translationResults字段 查询符合条件的  child_flag=1 and translationResults=null
    let querySql5 = `SELECT * FROM js_app_translation_child_task WHERE package_name = ? AND version = ? AND child_flag = 1 AND (translationResults IS NULL OR translationResults = '') `
    let res5 = await mysqlQueryUpdate(querySql5, [package_name, version])
    if (res5.length > 0) {
        console.log('进入第五步----------处理合并translationResults字段 有符合条件的')
        await processAndStoreTranslations(res5)
    }


    // 6.翻译任务结束了 把 js_app_translation_task表的  flag设置为1 已翻译  发飞书通知
    let setSql1 = `UPDATE js_app_translation_task  SET flag=1,update_time = '${utils.formatDate(new Date())}'  WHERE  package_name = '${package_name}' AND version = '${version}'`
    let setSqlFlag1 = await mysqlQuery(setSql1)
    let appNotice = {
        pk: package_name,
        version: version,
        type: 2,
    }
    await checkThresholdLimit(appNotice)
    console.log('setSqlFlag1-------执行了第六步')
})

async function processAndStoreTranslations(arr) {
    console.log('进入第五步---------processAndStoreTranslations')
    let dataList = await enrichTranslationResults(arr)
    dataList.forEach(async item => {
        console.log('-------执行了第五步')
        let translationResults = JSON.stringify(item.translationResults)
        let sql = `UPDATE js_app_translation_child_task  SET translationResults= ? WHERE  id =  ?`
        let data = [translationResults, item.id]
        let res = await mysqlQueryUpdate(sql, data)
    })
}


async function enrichTranslationResults(resList) {
    const translationsByLanguage = resList.reduce((acc, item) => {
        acc[item.target_language] = acc[item.target_language] || [];
        acc[item.target_language].push({
            string_content: item.string_content,
            translation_result: item.translation_result
        });
        return acc;
    }, {});

    return resList.map(item => {
        const currentLanguageTranslations = translationsByLanguage[item.target_language];

        const otherLanguageTranslations = resList
            .filter(otherItem => otherItem.string_content === item.string_content && otherItem.target_language !== item.target_language);

        // Create a Set to filter out duplicates
        const seenTranslations = new Set();

        // Combine current and other language translations
        const translationResults = [
            {
                targetLanguage: item.target_language,
                translationResult: item.translation_result
            },
            ...otherLanguageTranslations.map(otherItem => ({
                targetLanguage: otherItem.target_language,
                translationResult: otherItem.translation_result
            }))
        ].filter(obj => {
            const key = obj.targetLanguage + obj.translationResult;
            if (seenTranslations.has(key)) {
                return false;
            } else {
                seenTranslations.add(key);
                return true;
            }
        });

        return {
            ...item,
            translationResults
        };
    });
}


async function appTranslateTextAddContentTranslateTask(arr) {
    for (const task of arr) {
        await performTranslation(task);
    }
}


async function performTranslation(task) {
    console.log('performTranslation-------执行了第四步');

    const MAX_RETRIES = 3;
    const TIMEOUT_LIMIT = 5000; // 5 seconds

    let attempts = 0;

    while (attempts < MAX_RETRIES) {
        try {
            let text = normalizeContent(task.string_content);
            let lang = task.target_language.trim();
            let translateRes;
            const response = await translateForApp(lang, text); // 调用翻译API
            translateRes = response.data;

            if (translateRes.answer.includes(`${text} -->`) || translateRes.answer.includes(`${text} ->`)) {
                translateRes.answer = translateRes.answer.replace(`${text} -->`, "").replace(`${text} ->`, "");
            }
            translateRes.answer = translateRes.answer.replace(/&(?![a-zA-Z]{1,8};)/g, "&amp;");

            let answer = translateRes.answer;
            if (answer.includes("&amp;")) {
                answer = answer.replace(/&amp;/g, "&");
            }
            answer = answer.replace(/'/g, "\\'").replace(/＂/g, "\"");  //翻译结果

            //把翻译结果存进数据库
            let sql = `UPDATE js_app_translation_child_task SET translation_result = ?, child_flag = 1 WHERE id = ?`;
            let data = [answer, task.id];
            let res = await mysqlQueryUpdate(sql, data);

            console.log(`翻译结果已更新: task.id = ${task.id}`);
            return; // 成功后退出函数

        } catch (err) {
            console.log('翻译失败------------------重试')
            attempts++;
            console.error(`Error translating for language ${task.target_language.trim()}: ${err.message}. Attempt ${attempts} of ${MAX_RETRIES}`);

            if (attempts >= MAX_RETRIES) {
                console.error(`Failed to translate for task.id = ${task.id} after ${MAX_RETRIES} attempts.`);
                return; // 到达重试限制后退出函数
            }
            await new Promise(resolve => setTimeout(resolve, TIMEOUT_LIMIT)); // 在重试前等待一段时间
        }
    }
}

async function mysqlQueryUpdate(sql, data) {
    return new Promise((resolve, reject) => {
        pool.query(sql, data, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}

//消息卡片
async function checkThresholdLimit(appNotice) {
    //type = 1 上传成功  type = 2 翻译完成  type = 3 打包完成
    const { pk, version, type } = appNotice
    let token = await msgUtils.getTenantAccessToken();
    let msg_type = "interactive";
    // let id = utils.getGroupIdByType(appNotice.type);
    // let id = `oc_300d536417e7a4d6a47c27bc43b00bb0`;
    let id = `oc_a7a61d39ee67be54a2c36a3a564292b4`; // 翻译任务群
    let at = "";
    let content = '';
    if ((pk == 'all' || pk == 'all2' || pk == 'ins2') && type == 1) { //<at id="3581b3g8">(运营)</at> 罗可以
        at = `<at id="582bb54a">(产品)</at><at id="39d85c67">(运营)</at><at id="9c8364d1">(运营)</at>\n\n`
        content = `${pk}-${version} xml文件上传成功--请运营去后台点击翻译!\n操作时间:${moment(new Date()).tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")}`
    }
    if ((pk == 'all' || pk == 'all2' || pk == 'ins2') && type == 2) {
        at = `<at id="582bb54a">(产品)</at><at id="39d85c67">(运营)</at><at id="9c8364d1">(运营)</at>\n\n`
        content = `${pk}-${version} xml文件已翻译完成--请运营去后台校对无误后提交!\n操作时间:${moment(new Date()).tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")}`

    }
    if ((pk == 'all' || pk == 'all2' || pk == 'ins2') && type == 3) {
        at = `<at id="582bb54a">(产品)</at><at id="269eceeg">(研发)</at>\n\n`
        content = `${pk}-${version} xml文件已校对翻译打包完成--请开发去后台下载使用!\n操作时间:${moment(new Date()).tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")}`
    }

    let contentMsg = {
        config: { wide_screen_mode: true, update_multi: true },
        elements: [
            {
                tag: "div",
                text: {
                    content: `${at}${content}`,
                    tag: "lark_md",
                },
                extra: {
                    alt: { content: "", tag: "plain_text" },
                    img_key: "img_v2_f4f6fa23-e931-4dae-8ea2-c3d398656ddg",
                    tag: "img",
                },
            },
        ],
        header: {
            template: "turquoise",
            title: {
                content: `${pk}-version-${version}`,
                tag: "plain_text",
            },
        },
    };
    let jsonString = JSON.stringify(contentMsg);
    await msgUtils.sendMessage(id, msg_type, jsonString, token);
}
router.post('/downloadXML', (req, res) => {
    const { version, package_name } = req.body;

    // 基于请求的参数生成或查找文件路径
    const filePath = path.join(`/zj-manager/app-file/${package_name}/`, `${package_name}-${version}.zip`);
    console.log(filePath, 'filePath');

    // 检查文件是否存在
    fs.access(filePath, fs.constants.F_OK, (err) => {
        if (err) {
            console.error("File does not exist:", err);
            return res.status(404).send("File not found.");
        }

        console.log("File exists");

        // 文件存在，发送下载
        res.setHeader('Content-Type', 'application/zip');
        res.setHeader('Content-Disposition', `attachment; filename=${package_name}-${version}.zip`);
        res.download(filePath, `${package_name}-${version}.zip`, (err) => {
            if (err) {
                console.error("File send error:", err);
                res.status(500).send("Error downloading the file.");
            }
        });
    });
});


module.exports = router;
